package com.dd.cloud.user.service.menu.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dd.cloud.common.constants.ClientMenuConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.ObjectUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.vo.PageVo;
import com.dd.cloud.user.entity.menu.BannerImg;
import com.dd.cloud.user.mapper.menu.BannerImgMapper;
import com.dd.cloud.user.req.menu.AddBannerImgReq;
import com.dd.cloud.user.req.menu.GetBannerImgPageReq;
import com.dd.cloud.user.req.menu.UpdateBannerImgReq;
import com.dd.cloud.user.res.admin.source.BannerImgSystemPageRes;
import com.dd.cloud.user.service.menu.IBannerImgService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 轮播图 服务实现类
 * </p>
 *
 * @author czg
 * @since 2023-09-11
 */
@Service
public class BannerImgServiceImpl extends ServiceImpl<BannerImgMapper, BannerImg> implements IBannerImgService {
    /**
     * @param type:
     * @return List<BannerImg>
     * @description 获取轮播图列表
     * @author czg
     * @date 2023/9/12 10:19
     */
    @Override
    public List<BannerImg> getBannerImgList(Integer type) {
        QueryWrapper<BannerImg> qw = new QueryWrapper<>();
        if (type != null) {
            qw.lambda().eq(BannerImg::getType, type);
        }
        qw.lambda().eq(BannerImg::getStatus, ClientMenuConstants.BannerStatus.NORMAL).orderByAsc(BannerImg::getSort);
        return list(qw);
    }

    /**
     * @param req:
     * @return void
     * @description 添加banner图
     * @author czg
     * @date 2023/9/12 11:02
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addBannerImg(AddBannerImgReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        BannerImg bannerImg = new BannerImg();
        BeanUtils.copyProperties(req, bannerImg);
        int sort = cumSectionSort(req.getType(), req.getSort(), null);
        bannerImg.setSort(sort);
        if (bannerImg.getStatus() == null) {
            bannerImg.setStatus(ClientMenuConstants.BannerStatus.NORMAL);
        }
        String res = "";
        QueryWrapper<BannerImg> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerImg::getStatus, ClientMenuConstants.BannerStatus.NORMAL);
        int count = count(qw);
        if (count >= 6) {
            bannerImg.setStatus(ClientMenuConstants.BannerStatus.DISABLE);
            res = "超过6张banner图";
        }
        bannerImg.setCreateDate(LocalDateTime.now());
        bannerImg.setOperId(loginInfo.getId());
        bannerImg.setLastOperId(loginInfo.getId());
        boolean save = save(bannerImg);
        if (!save) {
            throw new ZekeException("添加失败");
        }
        getBaseMapper().updateBannerImgReorder(req.getType());
        return res;
    }

    /**
     * @param req:
     * @return void
     * @description 修改banner图
     * @author czg
     * @date 2023/9/12 11:03
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateBannerImg(UpdateBannerImgReq req) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        BannerImg byId = getById(req.getId());
        if (byId == null) {
            throw new ZekeException("数据不存在");
        }
        int sort = cumSectionSort(req.getType(), req.getSort(), byId.getSort());
        BeanUtils.copyProperties(req, byId);
        byId.setSort(sort);
        byId.setLastOperId(loginInfo.getId());
        byId.setUpdateDate(LocalDateTime.now());
        String res = "";
        if (req.getStatus() == ClientMenuConstants.BannerStatus.NORMAL) {
            QueryWrapper<BannerImg> qw = new QueryWrapper<>();
            qw.lambda().eq(BannerImg::getStatus, ClientMenuConstants.BannerStatus.NORMAL);
            qw.lambda().ne(BannerImg::getId, req.getId());
            int count = count(qw);
            if (count >= 6) {
                byId.setStatus(ClientMenuConstants.BannerStatus.DISABLE);
                res = "超过6张banner图";
            }
        }
        boolean update = updateById(byId);
        if (!update) {
            throw new ZekeException("修改失败");
        }
        getBaseMapper().updateBannerImgReorder(req.getType());
        return res;
    }

    /**
     * @param id:
     * @param status:
     * @return void
     * @description 修改banner图状态
     * @author czg
     * @date 2023/9/12 11:08
     */
    @Override
    public void updateBannerImgStatus(Integer id, Integer status) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        BannerImg byId = getById(id);
        if (byId == null) {
            throw new ZekeException("数据不存在");
        }
        if (status.equals(byId.getStatus())) {
            return;
        }
        if (!ObjectUtils.refrect(ClientMenuConstants.BannerStatus.class, status)) {
            throw new ZekeException(ZkExceptionEnum.STATUS_DATA_ERROR);
        }
        byId.setStatus(status);
        if (status == ClientMenuConstants.BannerStatus.NORMAL) {
            QueryWrapper<BannerImg> qw = new QueryWrapper<>();
            qw.lambda().eq(BannerImg::getStatus, ClientMenuConstants.BannerStatus.NORMAL);
            int count = count(qw);
            if (count >= 6) {
                throw new ZekeException(400, "超过6张banner图,无法进行显示操作");
            }
        }
        byId.setLastOperId(loginInfo.getId());
        byId.setUpdateDate(LocalDateTime.now());
        boolean update = updateById(byId);
        if (!update) {
            throw new ZekeException("修改失败");
        }
    }

    /**
     * @param req:
     * @return Page<BannerImg>
     * @description 分页获取banner图
     * @author czg
     * @date 2023/9/13 15:09
     */
    @Override
    public PageVo<BannerImgSystemPageRes> getBannerImgPage(GetBannerImgPageReq req) {
        if (StringUtils.isBlank(req.getStatus())) {
            req.setStatus("1,2");
        }
        PageVo<BannerImgSystemPageRes> pageVo = req.pageVoPojo();
        pageVo = getBaseMapper().queryBannerImgSystemPage(pageVo, req);
        QueryWrapper<BannerImg> qw = new QueryWrapper<>();
        qw.lambda().eq(BannerImg::getStatus, ClientMenuConstants.BannerStatus.NORMAL);
        int count = count(qw);
        pageVo.setExtend(count);
        return pageVo;
    }


    /**
     * banner图重排序
     *
     * @param type    图片类型
     * @param newSort 新排序位置
     * @param oldSort 旧排序位置
     * @return 目标位置
     */
    public int cumSectionSort(Integer type, Integer newSort, Integer oldSort) {
        if (oldSort == null) {
            //没有原位置, 为新增
            //先进行重排序
            getBaseMapper().updateBannerImgReorder(type);
            if (newSort == null) {
                QueryWrapper<BannerImg> qu = new QueryWrapper<>();
                qu.lambda().eq(BannerImg::getType, type).orderByDesc(BannerImg::getSort).ne(BannerImg::getStatus, ClientMenuConstants.BannerStatus.DELETE).last("limit 1");
                BannerImg content = getOne(qu);
                if (content == null) {
                    return 1;
                }
                return content.getSort() + 1;
            }
            UpdateWrapper<BannerImg> uw = new UpdateWrapper<>();
            uw.lambda().ge(BannerImg::getSort, newSort).ne(BannerImg::getStatus, ClientMenuConstants.BannerStatus.DELETE).setSql("`sort` = `sort` + 1");
            update(uw);
            return newSort;
        }
        if (newSort.equals(oldSort)) {
            return newSort;
        }
        //有原位置, 为修改, 只用修改两个位置之间的数据即可
        if (newSort > oldSort) {
            //后移
            UpdateWrapper<BannerImg> uw = new UpdateWrapper<>();
            uw.lambda().le(BannerImg::getSort, newSort).ge(BannerImg::getSort, oldSort).ne(BannerImg::getStatus, ClientMenuConstants.BannerStatus.DELETE).setSql("`sort` = `sort` - 1");
            update(uw);
            return newSort;
        } else {
            //前移
            UpdateWrapper<BannerImg> uw = new UpdateWrapper<>();
            uw.lambda().lt(BannerImg::getSort, oldSort).ge(BannerImg::getSort, newSort).ne(BannerImg::getStatus, ClientMenuConstants.BannerStatus.DELETE).setSql("`sort` = `sort` + 1");
            update(uw);
            return newSort;
        }
    }
}
